﻿using Anley.DomainDrivenDesign.Contract.Configuration;
using Anley.DomainDrivenDesign.Contract.Extension;
using Anley.DomainDrivenDesign.Contract.Helper;

namespace Anley.DomainDrivenDesign.Contract.Authorization;

/// <summary>
/// 授权帮助类
/// </summary>
public class AuthorizationHelper
{
    private readonly static JsonSerializerSettings jsonSerializerSettings;

    static AuthorizationHelper()
    {
        jsonSerializerSettings = new JsonSerializerSettings()
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            Formatting = Formatting.None
        };
    }

    /// <summary>
    /// 生成访问令牌
    /// </summary>
    public static string GenerateAccessToken(
        ICurrentUser currentUser)
    {
        // 头部
        var jwtHeader = new JwtHeader() { typ = "JWT", alg = "SM2" };
        var headerStr = JsonConvert.SerializeObject(jwtHeader, jsonSerializerSettings).StringToBase64String();
        // 载荷
        var authConfig = ServiceProviderHelper.ServiceProvider.GetRequiredService<IOptionsMonitor<AuthorizationConfiguration>>().CurrentValue;
        currentUser.ExpiredTime = DateTime.UtcNow.AddMinutes(authConfig.TokenExpire).GenerateTimestamp();
        var payloadStr = JsonConvert.SerializeObject(currentUser, jsonSerializerSettings).StringToBase64String();
        // 签名
        var encryptionHelper = ServiceProviderHelper.ServiceProvider.GetRequiredService<IEncryptionHelper>();
        var plainStr = $"{headerStr}.{payloadStr}";
        var signStr = encryptionHelper.SM2ServerSignature(plainStr);
        // 返回结果
        return $"{plainStr}.{signStr}";
    }

    /// <summary>
    /// 验证访问令牌
    /// </summary>
    /// <param name="jwtToken"></param>
    /// <param name="tokenUser"></param>
    public static bool VerifyAccessToken(
        string jwtToken,
        out ICurrentUser? tokenUser)
    {
        // 拆解
        var sections = jwtToken.Split('.');
        if (sections.Length != 3)
        {
            tokenUser = null;
            return false;
        }
        var headerStr = sections[0];
        var payloadStr = sections[1];
        var signStr = sections[2];
        // 验签
        var plainStr = $"{headerStr}.{payloadStr}";
        var encryptionHelper = ServiceProviderHelper.ServiceProvider.GetRequiredService<IEncryptionHelper>();
        if (!encryptionHelper.SM2ServerVerifySignature(plainStr, signStr))
        {
            tokenUser = null;
            return false;
        }
        // 解析当前用户
        tokenUser = TypeExtension.CreateInterfaceInstance<ICurrentUser>();
        payloadStr = payloadStr.Base64StringToString();
        JsonConvert.PopulateObject(payloadStr, tokenUser);
        // 验证有效期
        var timestamp = DateTime.UtcNow.GenerateTimestamp();
        if (tokenUser.ExpiredTime < timestamp)
        {
            tokenUser = null;
            return false;
        }
        // 返回结果
        return true;
    }
}